package com.ruicar.afs.cloud.afscase.dispatch.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.afscase.channel.entity.ChannelAuthorizeRegion;
import com.ruicar.afs.cloud.afscase.channel.entity.ChannelBaseInfo;
import com.ruicar.afs.cloud.afscase.channel.entity.ChannelRiskInfo;
import com.ruicar.afs.cloud.afscase.channel.service.ChannelAuthorizeRegionService;
import com.ruicar.afs.cloud.afscase.channel.service.ChannelBaseInfoService;
import com.ruicar.afs.cloud.afscase.channel.service.ChannelRiskInfoService;
import com.ruicar.afs.cloud.afscase.dispatch.DispatchContext;
import com.ruicar.afs.cloud.afscase.dispatch.annotation.Dispatch;
import com.ruicar.afs.cloud.afscase.dispatch.enums.DispatchTypeEnum;
import com.ruicar.afs.cloud.afscase.dispatch.service.DispatchBaseServcie;
import com.ruicar.afs.cloud.afscase.infomanagement.entity.*;
import com.ruicar.afs.cloud.afscase.infomanagement.service.*;
import com.ruicar.afs.cloud.afscase.paramconfmanagement.entity.CaseConfParam;
import com.ruicar.afs.cloud.afscase.paramconfmanagement.service.CaseConfParamService;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.IsAssignedEnum;
import com.ruicar.afs.cloud.common.rules.RuleHelper;
import com.ruicar.afs.cloud.common.rules.constants.RuleRunEnum;
import com.ruicar.afs.cloud.common.rules.dto.RuleRunResult;
import com.ruicar.afs.cloud.seats.entity.RegularValue;
import com.ruicar.afs.cloud.seats.service.RegularValueService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author cheng.bi
 */
@Slf4j
@Service
@Dispatch(name = "放款分单时间", dependsOn = "dispatchPriorLoanService", group = DispatchTypeEnum.LOAN)
public class DispatchTimeBeforeLoanService extends DispatchBaseServcie {

    @Autowired
    private CaseContractInfoService contractInfoService;

    @Autowired
    private CaseBaseInfoService caseBaseInfoService;

    @Autowired
    private RegularValueService valueService;

    @Autowired
    private CaseCarInfoService caseCarInfoService;

    @Autowired
    private CaseCarStyleDetailService carStyleDetailInfoService;

    @Autowired
    private ChannelBaseInfoService channelBaseInfoService;
    @Autowired
    private ChannelAuthorizeRegionService regionService;

    @Autowired
    private ChannelRiskInfoService channelRiskInfoService;

    @Autowired
    private CaseChannelInfoService channelInfoService;
    
    @Autowired
    private CaseConfParamService caseConfParamService;

    /**
     * 分单前实际处理方法
     *
     * @param context
     */
    public void process(DispatchContext context) {

        List<CaseContractInfo> passList = new ArrayList<CaseContractInfo>(); //收集可以启动的放款提交案件传递到下个服务进行处理
        // 获取所有的分单时间输出值
        List<RegularValue> valueList = valueService
                .list(Wrappers.<RegularValue>lambdaQuery().eq(RegularValue::getRuleType, "loanSplittingTime"));
        List<String> ruleList = valueList.stream().filter(s -> {
            String[] times = s.getValue().split("-");
            String startTime = times[0]; // 开始时间
            String endTime = times[1]; // 结束时间
            String timeNow = DateUtil.format(DateUtil.date(), "HH:mm");
            if (startTime.compareTo(timeNow) <= 0 && endTime.compareTo(timeNow) >= 0)
                return true;
            return false;
        }).map(s -> {
            return s.getId().toString();
        }).collect(Collectors.toList()); // 满足当前时间的规则
        log.info("符合当前时间的规则编号:{}", ruleList);
        /**
         //查找处于放款申请阶段放款队列的案件合同信息
         List<CaseContractInfo> contractList = contractInfoService.list(Wrappers.<CaseContractInfo>lambdaQuery()
         .eq(CaseContractInfo::getBusinessStage, BusinessStageEnum.LOAN_APPLY.getCode())
         .eq(CaseContractInfo::getApplyStatus, ApplyStatusEnum.LOAN_QUEUE.getState())
         .orderByDesc(CaseContractInfo::getIsTop)
         .orderByDesc(CaseContractInfo::getPriority).orderByAsc(CaseContractInfo::getCreateTime)); // 按照置顶，优先级，申请时间，排序获取case
         **/
        List<CaseContractInfo> contractList = (List) (Optional.ofNullable(context.get(LOAN_KEY)).orElse(new ArrayList()));
        contractList = contractList.stream().sorted(Comparator.nullsLast(Comparator.comparing(CaseContractInfo::getIsTop, Comparator.nullsLast(Comparator.reverseOrder())))
                .thenComparing(CaseContractInfo::getPriority, Comparator.nullsLast(Comparator.reverseOrder()))
                .thenComparing(CaseContractInfo::getCreateTime, Comparator.nullsLast(Comparator.naturalOrder()))).collect(Collectors.toList());

        // 获取所有的分单时间输出值
        if (contractList != null && !contractList.isEmpty()) {

            log.info("本次进行分单时间规则数据[{}]", contractList.size());
            for (CaseContractInfo contractInfo : contractList) {
                CaseBaseInfo baseInfo = caseBaseInfoService.getOne(
                        Wrappers.<CaseBaseInfo>lambdaQuery().eq(CaseBaseInfo::getApplyNo, contractInfo.getApplyNo()));
                JSONObject jsonObject = new JSONObject();
                /**字段待扩充*/
                /**金融产品*/
                jsonObject.put("productId", String.valueOf(baseInfo.getProductId()));
                /**业务类型*/
                jsonObject.put("businessType", baseInfo.getBusinessType());
                /**车辆类型*/
                jsonObject.put("carType", baseInfo.getCarType());
                /**车辆属性*/
                jsonObject.put("carNature", baseInfo.getCarNature());
                /**运营方式*/
                jsonObject.put("operateWay", baseInfo.getOperateWay());
                /**挂靠方式*/
                jsonObject.put("affiliatedWay", baseInfo.getAffiliatedWay());
                CaseCarInfo caseCarInfo = caseCarInfoService.getOne(Wrappers.<CaseCarInfo>query().lambda().eq(CaseCarInfo::getApplyNo, baseInfo.getApplyNo()));
                if (ObjectUtil.isNotNull(caseCarInfo)) {
                    /**车辆级别*/
                    jsonObject.put("carBodyClass", caseCarInfo.getCarBodyClass());
                    /**车型*/
                    jsonObject.put("modelCode", caseCarInfo.getModelCode());
                    /**购车地省份*/
                    jsonObject.put("purchaseProvince", caseCarInfo.getPurchaseCity());
                    /**购车地城市*/
                    jsonObject.put("purchaseCity", caseCarInfo.getPurchaseCity());
                    List<CaseCarStyleDetail> cartyleDetailInfo = carStyleDetailInfoService.list(Wrappers.<CaseCarStyleDetail>query().lambda().eq(CaseCarStyleDetail::getCarId, caseCarInfo.getId()));
                    if (cartyleDetailInfo != null && !cartyleDetailInfo.isEmpty()) {
                        /**是否新能源*/
                        String isGreen = cartyleDetailInfo.get(0).getIsGreen();
                        jsonObject.put("isGreen", isGreen);
                    }
                }
                CaseChannelInfo caseChannelInfo = channelInfoService.getOne(Wrappers.<CaseChannelInfo>query().lambda().eq(CaseChannelInfo::getApplyNo, baseInfo.getApplyNo()));
                if (ObjectUtil.isNotNull(caseChannelInfo)) {
                    /**经销商名称*/
                    jsonObject.put("dealerName", caseChannelInfo.getDealerName());
                    ChannelBaseInfo channelBaseInfo = channelBaseInfoService.getOne(Wrappers.<ChannelBaseInfo>query().lambda().eq(ChannelBaseInfo::getChannelCode, caseChannelInfo.getDealerNo()));
                    if (ObjectUtil.isNotNull(channelBaseInfo)) {
                        /**合作商注册地址*/
                        jsonObject.put("channelAddress", channelBaseInfo.getChannelAddress());
                        /**经销商省份*/
                        jsonObject.put("channelProvince", channelBaseInfo.getChannelProvince());
                        /**经销商城市*/
                        jsonObject.put("channelCity", channelBaseInfo.getChannelCity());
                        /**渠道归属*/
                        jsonObject.put("channelBelong", channelBaseInfo.getChannelBelong());
                        ChannelRiskInfo channelRiskInfo = channelRiskInfoService.getOne(Wrappers.<ChannelRiskInfo>query().lambda()
                                .eq(StringUtils.isNotBlank(caseChannelInfo.getDealerNo()), ChannelRiskInfo::getChannelId, channelBaseInfo.getChannelId())
                                .eq(StringUtils.isNotBlank(channelBaseInfo.getBusinessType()), ChannelRiskInfo::getBusinessType, baseInfo.getBusinessType()));
                        if (ObjectUtils.isNotEmpty(channelRiskInfo)) {
                            String qualityGrade = channelRiskInfo.getQualityGrade();
                            /**优质等级*/
                            jsonObject.put("qualityGrade", qualityGrade);
                            /**合作商评级*/
                            jsonObject.put("channelGrade", channelRiskInfo.getChannelGrade());
                        }
                        List<ChannelAuthorizeRegion> list = regionService.list(Wrappers.<ChannelAuthorizeRegion>query().lambda().eq(ChannelAuthorizeRegion::getChannelId, channelBaseInfo.getChannelId()));
                        if (list != null && !list.isEmpty()) {
                            String practicesProvince = "";
                            String practicesCity = "";
                            for (ChannelAuthorizeRegion region : list) {
                                if (IsAssignedEnum.YES.getCode().equals(region.getParentId()) && IsAssignedEnum.YES.getCode().equals(region.getIsParent())) {
                                    practicesProvince = practicesProvince + region.getCode() + ",";
                                }
                                if (IsAssignedEnum.NO.getCode().equals(region.getIsParent())) {
                                    practicesCity = practicesCity + region.getCode() + ",";
                                }
                            }
                            /**展业省份*/
                            jsonObject.put("practicesProvince", practicesProvince.substring(0, practicesProvince.length() - 1));
                            /**展业城市*/
                            jsonObject.put("practicesCity", practicesCity.substring(0, practicesCity.length() - 1));
                        }
                    }
                }
                // 执行分单时间规则
                RuleRunResult result = RuleHelper.runRule(jsonObject, "loanSplittingTime", false, RuleRunEnum.SERIAL);
                Boolean flag = result.getHit();
                if (flag) {
                    if (!result.getResults().stream().anyMatch(s -> ruleList.contains(s.getRuleNo()))) {
                        log.info("申请编号: {}不满足时间规则，跳过", contractInfo.getApplyNo());
                        continue;
                    }
                } else { //没有命中 说明没有与之匹配的规则 则调用分单时间参数进行判断
                	 CaseConfParam confParam = caseConfParamService
                             .getOne(Wrappers.<CaseConfParam>query().lambda().eq(CaseConfParam::getParamType, "DISPATCH_TIME").eq(CaseConfParam::getParamStatus, "yes"));
                	if(ObjectUtils.isNotEmpty(confParam.getParamValue())) {
                		String [] timeStr = confParam.getParamValue().split("-");
                		String timeNow = DateUtil.format(DateUtil.date(), "HH:mm");
                        if (timeStr[0].compareTo(timeNow) > 0 || timeStr[1].compareTo(timeNow) < 0) {
                        	continue;
                        }
                	}
                }
                //纳入可执行参数
                log.info("加载可分单的数据，申请编号:[{}],", baseInfo.getApplyNo());
                passList.add(contractInfo);
                context.put(contractInfo.getId(), jsonObject);

            }
            log.info("符合分单的数据总条数为:[{}]", passList.size());
            context.put(LOAN_KEY, passList);
        }
    }
}
